//Francisco "Kiko" Olvera
//holds array of 50 tiles total
//board consists of a 2D array of tile pointers
//keeps track of current and extra tiles at all times
//Board.h

#pragma once
#include "Tile.h"
#include "Mesh.h"
#include "Structures.h"
#include "Definitions.h"
#include "ENUM.h"
#include "PUSwap.h"
#include "PUWallPass.h"
#include "PUExtraTurn.h"
#include "Light.h"
#include "Material.h"
#include "PURotate.h"
#include "PUSearchForCard.h"
#include "PUShiftExtraTile.h"

class Artifact;
class Player;

class Board
{
private:
	//7*7 board + 1 extra = 50 tiles
	//first 4 reserved for spawn points
	//last 12 are immovable THREEWAY pieces
	Tile tile[NUM_TILES];
	Tile* map[NUM_ROWS_AND_COLUMNS][NUM_ROWS_AND_COLUMNS];
	Tile * extra;
	int extraPos;
	Tile * currentTile;
	Mesh straightMesh, elbowMesh, threewayMesh;
	Artifact* artifact;
	/************************
	*** Will's light code ***
	*************************/
	Light*		light;

private:
	//powerups are assigned in spawnTiles()
	PUSwap swap;
	PUSearchForCard searchForCard;
	PUShiftExtraTile ShiftExTile;
	PUExtraTurn ExTurn;
	PU_Rotate rotate;
	PUWallPass wallPass;
private:
	bool picked[NUM_TILES];
private:
	//Board Manipulation
	//returns pointer to newly placed tile
	Tile* shiftColumnDown(int);
	Tile* shiftColumnUp(int);
	Tile* shiftRowLeft(int);
	Tile* shiftRowRight(int);
private:
	void spawnTiles();
	void placeArtifacts();
	void placeTile(Tile*, int);
	void pickTile(int, int);
	void fillBoard();
	void DrawExtra();
private:
	void secureTilePositions();
public:
	Board();
	~Board();
public:
	void Init(Artifact*);
	void initLight(int, int *, Player*);
	void Update(Input *);
	void Render();
public:
	//Sets
	inline void setCurrentTile(Tile* newTile)	{currentTile = newTile;}
	void setCurrentTile(XY);
public:
	//extra tile functions
	inline void shiftExtraPosUp()				{extraPos++; if(extraPos > LEFT1) extraPos = 0;}
	inline void shiftExtraPosDown()				{extraPos--; if(extraPos < 0) extraPos = LEFT1;}
	void ExtraTileOut();
	void RotateExtraTileClock();
	void RotateExtraTileCounterClock();
public:
	//Gets
	inline Tile* getCurrentTile()	{return currentTile;}
	inline Tile* getTile(XY pos)	{return map[pos.X][pos.Y];}
	inline Tile* getExtraTile()		{return extra;}
	//Neighbor Checking
	Tile* getN();
	Tile* getS();
	Tile* getE();
	Tile* getW();
public:
	Tile* getRealNorth();
	Tile* getRealSouth();
	Tile* getRealEast();
	Tile* getRealWest();
public:
	//returns pointer to newly placed tile
	Tile* boardShift();
};